package com.director.core.json.impl.gson;

import com.director.core.DirectMethod;
import com.director.core.DirectTransactionData;
import com.director.core.DirectTransactionResult;
import com.director.core.PollingProvider;
import com.director.core.RemotingProvider;
import com.director.core.ResultWithStrategy;
import com.director.core.json.JsonParser;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * Author: Simone Ricciardi
 * Date: 3-giu-2010
 * Time: 14.43.21
 */
public class GsonParser implements JsonParser {

   private Gson gson;

   private List<GsonBuilderConfigurer> configurerList = new ArrayList<GsonBuilderConfigurer>();

   @Override
   public String format(Object object) {
      return this.build().toJson(object);
   }

   @Override
   public <T> T parse(String json, Class<T> type) {
      return this.build().fromJson(json, type);
   }

   @Override
   public DirectTransactionResult buildResult(DirectMethod directMethod, Object result) {
      return new GsonTransactionResult(this.build(), directMethod, result);
   }

   public void addConfigurer(GsonBuilderConfigurer configurer) {
      this.configurerList.add(configurer);
   }

   private Gson build() {
      if(this.gson == null) {
         this.gson = this.configure().create();
      }
      return this.gson;
   }

   private GsonBuilder configure() {
      GsonBuilder gsonBuilder = new GsonBuilder()
         .setDateFormat("yyyy-MM-DD'T'hh:mm:ss")
         .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT)
         .addSerializationExclusionStrategy(new TransactionDataExclusionStrategy())
         .registerTypeAdapter(DirectTransactionData.class, new TransactionDataTypeAdapter())
         .registerTypeAdapter(GsonTransactionResult.class, new TransactionResultTypeAdapter())
         .registerTypeAdapter(ResultWithStrategy.class, new ResultWithStrategyTypeAdapter())
         .registerTypeAdapter(RemotingProvider.class, new RemotingProviderTypeAdapter())
         .registerTypeAdapter(PollingProvider.class, new PollingProviderTypeAdapter());

      for(GsonBuilderConfigurer configurer : this.configurerList) {
         configurer.config(gsonBuilder);
      }

      return gsonBuilder;
   }
}
